package com.zmn.oms.admin.controller.work.modify;

import com.alibaba.fastjson.JSONArray;
import com.github.ltsopensource.core.json.JSON;
import com.google.common.collect.Lists;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.admin.controller.work.WorkBaseController;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.enums.RefundTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.MoneyUtil;
import com.zmn.oms.model.dto.work.refund.RefundVoucherDTO;
import com.zmn.oms.model.dto.work.refund.VoucherDataDTO;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.refund.OrderWorkRefundDetail;
import com.zmn.oms.model.vo.work.refund.OcrBankVO;
import com.zmn.oms.model.vo.work.refund.OcrRefundVoucherVO;
import com.zmn.oms.model.vo.work.refund.RefundBankVO;
import com.zmn.oms.model.vo.work.refund.RefundOrderWorkPayVO;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.refund.OrderWorkRefundDetailService;
import com.zmn.oms.zmn.business.interfaces.pay.OrderPayBService;
import com.zmn.oms.zmn.business.interfaces.work.orderpay.ZsOrderPayBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.tapi.common.baidu.api.IocrRecogniseDTO;
import com.zmn.tapi.common.baidu.api.RetDataDTO;
import com.zmn.tapi.dubbo.interfaces.baidu.BaiduAiRemoteService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * 类描述：退款金额
 * @author liuying
 * @date 2018/12/17 20:18
 */
@Controller
@RequestMapping("/work/modify")
public class WorkRefundVoucherController extends WorkBaseController {

    @Autowired
    OrderPayService orderPayService;
    @Autowired
    OrderPayBService orderPayBService;
    @Autowired
    ZsOrderPayBService zsOrderPayBService;
    @Autowired
    OrderWorkRefundDetailService refundDetailService;

    @Reference(version = com.zmn.tapi.dubbo.DubboConsts.INTERFACE_VERSION, check = false)
    BaiduAiRemoteService baiduAiRemoteService;

    /**
     * ocr识别银行数据匹配
     * key:正则表达式
     * value:银行数据
     */
//    private static final Map<String, OcrBankVO> ocrBankVOMap = Maps.newHashMap();
//    static {
//        ocrBankVOMap.put("建设.*1662|1662.*建设", new OcrBankVO("6217003760166071662","中国建设银行"));
//        ocrBankVOMap.put("邮政.*3465|3465.*邮政", new OcrBankVO("6221806900013423465","中国邮政储蓄银行"));
//        ocrBankVOMap.put("农村.*7662|7662.*农村", new OcrBankVO("6214656008127662","中国农村商业银行"));
//    }

    private static List<RefundBankVO> REFUND_BANK_VO_LIST = Lists.newArrayListWithExpectedSize(3);
    static {
        REFUND_BANK_VO_LIST.add(RefundBankVO.builder().account("6217003760166071662").accountBank("中国建设银行")
                .name("建设银行-1662").ocrPattern("建设.*1662|1662.*建设").build());
        REFUND_BANK_VO_LIST.add(RefundBankVO.builder().account("622908343093574414").accountBank("兴业银行股份有限公司重庆自由贸易试验区分行")
                .name("兴业银行-4414").ocrPattern("兴业.*4414|4414.*兴业").build());
        REFUND_BANK_VO_LIST.add(RefundBankVO.builder().account("622908343093574315").accountBank("兴业银行股份有限公司重庆自由贸易试验区分行")
                .name("兴业银行-4315").ocrPattern("兴业.*4315|4315.*兴业").build());
    }

    /**
     * 退款凭证
     */
    @RequestMapping(value = "/refundVoucher")
    public ModelAndView refund(Long orderId, Long workId, Integer moduleId) {
        ModelAndView mv = new ModelAndView("work/modify/refundVoucher");
        mv.addObject("orderId", orderId);
        mv.addObject("workId", workId);
        mv.addObject("moduleId", moduleId);

        // 退款信息
        List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkIdsAndTradeTypeSrc(orderId, Lists.newArrayList(workId), PayConsts.PAY_TRADE_TYPE_REFUND);
        if (CollectionUtil.isNullOrEmpty(orderPays)) {
            return mv;
        }
        OrderPay orderPay = orderPays.get(0);
        logger.info("{}WorkRefundVoucherController.refund orderPay={}", workId, JSON.toJSONObject(orderPay));
        RefundOrderWorkPayVO refundOrderWorkPayVO = BeanMapper.map(orderPay, RefundOrderWorkPayVO.class);
        refundOrderWorkPayVO.setPayTargetChanneName(RefundTypeEnum.getRefundTypeName(refundOrderWorkPayVO.getPayTargetChannelId()));
        logger.info("{}WorkRefundVoucherController.refund refundOrderWorkPayVO={}", workId, JSON.toJSONObject(refundOrderWorkPayVO));

        OrderWorkRefundDetail refundDetail = refundDetailService.findOrderWorkRefundDetailByOrderIdAndWorkId(orderId, workId);
        if (!Objects.isNull(refundDetail)) {
            refundOrderWorkPayVO.setRefundPoundage(refundDetail.getRefundPoundage());
            refundOrderWorkPayVO.setRefundVoucherRemark(refundDetail.getRefundVoucherRemark());
        }
        if (StringUtil.isNotBlank(orderPay.getRefundImageData())) {
            List<VoucherDataDTO> voucherDataDTOS = JSONArray.parseArray(orderPay.getRefundImageData(), VoucherDataDTO.class);
            refundOrderWorkPayVO.setRefundVoucherData(voucherDataDTOS);
        } else {
            refundOrderWorkPayVO.setRefundPoundage(null);
        }
        mv.addObject("refundOrderWorkPayVO", refundOrderWorkPayVO);
        mv.addObject("refundBankVoList", REFUND_BANK_VO_LIST);
        return mv;
    }

    /**
     * 保存退款凭证
     */
    @RequestMapping(value = "/save/refundVoucher")
    @ResponseBody
    public ResultDTO saveRefundVoucher(@RequestBody RefundVoucherDTO refundVoucherDTO) {
        try {
            orderPayBService.saveRefundVoucher(refundVoucherDTO);
            return ResultDTO.success(refundVoucherDTO);
        } catch (OmsBaseException e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail("保存退款凭证失败");
        }
    }

    /**
     * ocr识别
     */
    @RequestMapping(value = "/ocr/refundVoucher")
    @ResponseBody
    public ResultDTO ocrRefundVoucher(String refundVoucherUrl) {
        try {
            OcrRefundVoucherVO ocrRefundVoucherVO = new OcrRefundVoucherVO();

            logger.info("baiduAiRemoteService.iocrRecognise refundVoucherUrl={}", refundVoucherUrl);
            ResponseDTO<IocrRecogniseDTO> responseDTO = baiduAiRemoteService.iocrRecognise(refundVoucherUrl);
            logger.info("baiduAiRemoteService.iocrRecognise responseDTO={}", JSON.toJSONString(responseDTO));
            if (!responseDTO.isSuccess() || Objects.isNull(responseDTO.getData())) {
                return ResultDTO.fail("退款凭证信息提取失败，请自行填写");
            }

            IocrRecogniseDTO ocrData = responseDTO.getData();
            for (RetDataDTO retDataDTO : ocrData.getRet()) {
                if ("凭证号".equals(retDataDTO.getWord_name())) {
                    ocrRefundVoucherVO.setRefundNo(retDataDTO.getWord());
                } else if ("手续费".equals(retDataDTO.getWord_name()) && MoneyUtil.regex(retDataDTO.getWord())) {
                    ocrRefundVoucherVO.setRefundPoundage(new BigDecimal(retDataDTO.getWord()));
                } else if ("打款银行".equals(retDataDTO.getWord_name())) {
                    this.patternBank(retDataDTO.getWord(), ocrRefundVoucherVO);
                }
            }
            return ResultDTO.success(ocrRefundVoucherVO);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail("退款凭证信息提取失败，请自行填写");
        }
    }

    private void patternBank(String context, OcrRefundVoucherVO ocrRefundVoucherVO) {
        if (StringUtil.isBlank(context)) {
            return;
        }
        for (RefundBankVO refundBankVO : REFUND_BANK_VO_LIST) {
            Pattern p = Pattern.compile(refundBankVO.getOcrPattern());
            if (p.matcher(context).find()) {
                ocrRefundVoucherVO.setPayerThirdAccount(refundBankVO.getAccount());
                ocrRefundVoucherVO.setPayerThirdAccountBank(refundBankVO.getAccountBank());
                return;
            }
        }
    }
}
